using System;
using System.Collections.Generic;

namespace System.Data
{
	public sealed class DataRowComparer<TRow> : IEqualityComparer<TRow> where TRow : DataRow
	{
		static readonly DataRowComparer<TRow> default_instance = new DataRowComparer<TRow> ();

		public static DataRowComparer<TRow> Default {
			get { return default_instance; }
		}

		private DataRowComparer ()
		{
		}

		// LAMESPEC: neither of the parameters throws ArgumentNullException if it's null
		public bool Equals (TRow leftRow, TRow rightRow)
		{
			if (object.ReferenceEquals (leftRow, rightRow))
				return true;
			
			if (leftRow == null || rightRow == null)
				return false;
			
			int columnCount = leftRow.Table.Columns.Count;
			if (columnCount != rightRow.Table.Columns.Count)
				return false;
			
			for (int i = 0; i < columnCount; i++)
				if (!ColumnsEqual (leftRow[i], rightRow[i]))
					return false;
			return true;
		}

		bool ColumnsEqual (object leftCol, object rightCol)
		{
			if (object.ReferenceEquals (leftCol, rightCol))
				return true;
			
			if (leftCol == null || rightCol == null)
				return false;
			
			ValueType vt = leftCol as ValueType;
			if (vt != null && vt.Equals (rightCol))
				return true;
			
			return leftCol.Equals (rightCol);
		}

		public int GetHashCode (TRow row)
		{
			if (row == null)
				throw new ArgumentNullException ("row");
			
			DataTable table = row.Table;
			if (table == null)
				throw new ArgumentException ("The source DataRow objects does not belong to a DataTable.");
			
			DataColumnCollection columns = table.Columns;
			int columnCount = columns.Count;
			if (columnCount == 0)
				return 0;
			
			int ret = 0;
			object o;
			for (int i = 0; i < columnCount; i++) {
				o = row[i];
				if (o == null)
					continue;
				
				ret ^= o.GetHashCode ();
			}
			
			return ret;
		}
	}
}
